package com.gufe.service.admin.impl.preReserve;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.gufe.dto.adminPreReserve.PreReserveMembersExcelDTO;
import com.gufe.dto.adminPreReserve.PreReservePageMembersDTO;
import com.gufe.dto.prereserve.BasicInfoDTO;
import com.gufe.dto.prereserve.PreReserveInfoDTO;
import com.gufe.dto.prereserve.UpdateInfoDTO;
import com.gufe.entity.*;
import com.gufe.exception.NullDataException;
import com.gufe.mapper.admin.preReserve.PreReserveMemberMapper;
import com.gufe.result.PageResult;
import com.gufe.service.admin.preReserve.PreReserveMemberService;
import com.gufe.utils.CamelToSnake;
import com.gufe.vo.adminPreReserve.PreReserveMemberDetialVO;
import com.gufe.vo.adminPreReserve.PreReservePageMemberVO;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Slf4j
@Service
public class PreReserveMemberServiceImpl implements PreReserveMemberService {

    @Autowired
    PreReserveMemberMapper preReserveMemberMapper;
    // 定义所需的时间格式
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    /*获取单个学生的详细简历信息*/
    @Override
    public PreReserveMemberDetialVO getMemberDetialInfo(String studentId) {


        //根据学号得到userID
        Integer userId = preReserveMemberMapper.getUserIdByStudentId(studentId);
        //得到基础信息
        BasicInfo basicInfo = preReserveMemberMapper.getBasicInfo(userId);
        //得到军事兴趣社团类信息
        MilitaryInfo militaryInfo = preReserveMemberMapper.getMilitaryInfo(userId);
        //得到服役信息
        RetiredInfo retiredInfo = preReserveMemberMapper.getRetiredInfo(userId);
        //得到个人学习经历信息
        StudyExperienceInfo studyExperienceInfo = preReserveMemberMapper.getStudentExperienceInfo(userId);
        //得到预储信息
        PreEnlistmentInfo preEnlistmentInfo = preReserveMemberMapper.getPreEnlistmentInfo(userId);
        //封账vo返回
        PreReserveMemberDetialVO vo = new PreReserveMemberDetialVO();
        if (basicInfo != null) {
            BeanUtils.copyProperties(basicInfo, vo);
        }
        if (militaryInfo != null) {
            BeanUtils.copyProperties(militaryInfo, vo);
        }
        if (retiredInfo != null) {
            BeanUtils.copyProperties(retiredInfo, vo);
        }
        if (studyExperienceInfo != null) {
            BeanUtils.copyProperties(studyExperienceInfo, vo);
        }
        if (preEnlistmentInfo != null) {
            BeanUtils.copyProperties(preEnlistmentInfo, vo);
        }
        return vo;
    }


    /*条件分页查询*/
    @Override
    public PageResult getPageMembers(PreReservePageMembersDTO preReservePageMembersDTO) {
        PageHelper.startPage(preReservePageMembersDTO.getPage(), preReservePageMembersDTO.getPageSize());
        Page<PreReservePageMemberVO> page = preReserveMemberMapper.getPageMembers(preReservePageMembersDTO);
        return new PageResult(page.getTotal(), page.getResult());
    }


    /*导出单个学生Excel详细信息*/
    @Override
    public void getMemberExcelInfo(String studentId, HttpServletResponse response) {
        // 得到学生对象信息
        PreReserveMemberDetialVO preReserveMemberDetialVO = getMemberDetialInfo(studentId);

        // 通过POI将数据写入Excel文件
        InputStream excelModuleStream = this.getClass().getClassLoader().getResourceAsStream("module/预储信息采集表.xlsx");

        try {
            // 基于模板新建一个Excel文件
            XSSFWorkbook excel = new XSSFWorkbook(excelModuleStream);

            // 获取sheet页
            XSSFSheet sheet = excel.getSheet("Sheet1");

            createExcelSheet(sheet, preReserveMemberDetialVO);

            // 获取请求响应的输出流
            ServletOutputStream outputStream = response.getOutputStream();
            // 将excel文件输出，即客户端下载
            excel.write(outputStream);

            // 关流
            outputStream.close();
            excel.close();
            excelModuleStream.close();

        } catch (IOException e) {
            throw new RuntimeException("导出 Excel 失败", e);
        }
    }


    //填充单个学生信息到EXcel的sheet表中
    private void createExcelSheet(XSSFSheet sheet, PreReserveMemberDetialVO preReserveMemberDetialVO) {

        try {
            // 填充基本信息
            XSSFRow row = sheet.getRow(3);
            row.getCell(1).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getName(), "")); // 姓名
            row.getCell(3).setCellValue(preReserveMemberDetialVO.getGender() != null ? (preReserveMemberDetialVO.getGender() == 1 ? "男" : "女") : ""); // 性别
            row.getCell(5).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getIdCard(), "")); // 身份证号码
            row.getCell(7).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getPoliticalAffiliation(), "")); // 政治面貌


            // 头像URL下载并插入Excel
            String profilePictureUrl = preReserveMemberDetialVO.getProfilePicture();
            if (profilePictureUrl != null && !profilePictureUrl.isEmpty()) {
                byte[] imageBytes;
                try {
                    imageBytes = downloadImage(profilePictureUrl);  // 下载头像图片
                } catch (IOException e) {
                    log.info("图片{}下载失败，使用默认图片", profilePictureUrl);
                    imageBytes = this.getClass().getClassLoader().getResourceAsStream("img/default.jpg").readAllBytes(); // 类路径默认图片
                }

                int pictureIdx = sheet.getWorkbook().addPicture(imageBytes, Workbook.PICTURE_TYPE_JPEG);  // 添加图片到工作簿

                // 获取图片的实际尺寸
                BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(imageBytes));
                int imageWidth = bufferedImage.getWidth();
                int imageHeight = bufferedImage.getHeight();

                // 获取合并单元格的宽度和高度（以像素为单位）
                float cellWidth = sheet.getColumnWidthInPixels(8);  // 第8列的宽度（像素）
                float cellHeight = 0;
                for (int i = 2; i <= 5; i++) {
                    cellHeight += sheet.getRow(i).getHeightInPoints() * 96 / 72;  // 将点转换为像素
                }

                // 计算缩放比例
                double widthRatio = (double) cellWidth / imageWidth;  // 图片宽度与单元格宽度的比例
                double heightRatio = (double) cellHeight / imageHeight;  // 图片高度与单元格高度的比例
                double scale = Math.min(widthRatio, heightRatio);  // 获取最小缩放比例，确保图片在单元格内

                // 在单元格中插入图片
                XSSFDrawing drawing = sheet.createDrawingPatriarch();
                XSSFClientAnchor anchor = sheet.getWorkbook().getCreationHelper().createClientAnchor();

                // 设置图片插入位置（从第2行开始，到第5行结束）高度宽度固定后指定起始就行
                anchor.setRow1(2);  // 图片开始行（第2行）
                anchor.setCol1(8);  // 图片开始列
                anchor.setCol2(9);  // 图片结束列
                anchor.setRow2(6);  // 图片结束行（第5行）
                anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);  // 图片锚定到单元格，不浮动

                XSSFPicture picture = drawing.createPicture(anchor, pictureIdx);
                picture.resize(1);  // 禁用默认缩放，手动设置图片尺寸

                // 手动调整图片尺寸以铺满单元格
                double scaledWidth = imageWidth * scale;
                double scaledHeight = imageHeight * scale;

                // 计算图片在单元格中的偏移量（居中显示）
                double offsetX = (cellWidth - scaledWidth) / 2;
                double offsetY = (cellHeight - scaledHeight) / 2;

                // 调整图片位置和尺寸
                anchor.setDx1((int) (offsetX * 9525));  // 将像素转换为EMU单位
                anchor.setDy1((int) (0));  // 从第2行的顶部开始，不需要垂直偏移
                anchor.setDx2((int) ((cellWidth - offsetX) * 9525));
                anchor.setDy2((int) (cellHeight * 9525));  // 图片高度铺满单元格
            }

            row = sheet.getRow(4);
            row.getCell(1).setCellValue(preReserveMemberDetialVO.getBirthDate() != null ? preReserveMemberDetialVO.getBirthDate().format(formatter) : ""); // 出生日期
            row.getCell(3).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getNationality(), "")); // 民族
            row.getCell(5).setCellValue(preReserveMemberDetialVO.getMaritalStatus() != null ? (preReserveMemberDetialVO.getMaritalStatus() == 1 ? "未婚" : "已婚") : ""); // 婚姻状况
            row.getCell(7).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getReligiousAffiliation(), "")); // 宗教信仰

            row = sheet.getRow(5);
            row.getCell(1).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getNativePlace(), "")); // 籍贯
            row.getCell(3).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getHomeAddress(), "")); // 家庭住址
            row.getCell(6).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getMailingAddress(), "")); // 邮寄地址

            row = sheet.getRow(6);
            row.getCell(1).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getCollege(), "")); // 所在学院
            row.getCell(3).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getMajor(), "")); // 所学专业
            row.getCell(5).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getStudentId(), "")); // 学生ID
            row.getCell(7).setCellValue(preReserveMemberDetialVO.getScienceOrHumanities() != null ? (preReserveMemberDetialVO.getScienceOrHumanities() == 1 ? "理科" : "文科") : ""); // 理科或文科

            row = sheet.getRow(7);
            row.getCell(1).setCellValue(getIntValueOrDefault(preReserveMemberDetialVO.getGrade(), 0)); // 年级
            row.getCell(3).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getClassName(), "")); // 班级名称
            row.getCell(5).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getTelephone(), "")); // 联系方式
            row.getCell(7).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getQq(), "")); // QQ号

            // 填充体育成绩
            row = sheet.getRow(8);
            row.getCell(3).setCellValue(getDoubleValueOrDefault(preReserveMemberDetialVO.getHighSchoolPhysicalGrade(), 0.0)); // 高中体育成绩
            row.getCell(7).setCellValue(getDoubleValueOrDefault(preReserveMemberDetialVO.getUniversityPhysicalGrade(), 0.0)); // 大学体育成绩

            // 填充职业证书和职务
            row = sheet.getRow(9);
            row.getCell(1).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getProfessionalCertificates(), "")); // 专业证书
            row = sheet.getRow(10);
            row.getCell(1).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getClassPosition(), "")); // 班级职务
            row.getCell(3).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getClubName(), "")); // 所属社团
            row.getCell(5).setCellValue(preReserveMemberDetialVO.getClubJoinDate() != null ? preReserveMemberDetialVO.getClubJoinDate().format(formatter) : ""); // 加入社团时间
            row.getCell(7).setCellValue(preReserveMemberDetialVO.getClubLeaveDate() != null ? preReserveMemberDetialVO.getClubLeaveDate().format(formatter) : ""); // 离开社团时间

            // 高中信息
            row = sheet.getRow(11);
            row.getCell(1).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getHighSchoolName(), "")); // 高中名称
            row.getCell(5).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getHighSchoolAddress(), "")); // 高中地址
            row.getCell(8).setCellValue(preReserveMemberDetialVO.getHighSchoolSubjectType() != null ? (preReserveMemberDetialVO.getHighSchoolSubjectType() == 1 ? "理科" : "文科") : ""); // 高中学科类型

            // 填充军事俱乐部信息
            row = sheet.getRow(13);
            row.getCell(1).setCellValue(preReserveMemberDetialVO.getIsMilitaryClubMember() != null ? (preReserveMemberDetialVO.getIsMilitaryClubMember() == 1 ? "是" : "否") : ""); // 是否为军事俱乐部成员
            row.getCell(3).setCellValue(preReserveMemberDetialVO.getMilitaryClubJoinDate() != null ? preReserveMemberDetialVO.getMilitaryClubJoinDate().format(formatter) : ""); // 军事俱乐部加入日期
            row.getCell(5).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getMilitaryClubName(), "")); // 军事俱乐部名称
            row.getCell(7).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getMilitaryClubPosition(), "")); // 军事俱乐部职务
            row = sheet.getRow(14);
            row.getCell(1).setCellValue(getDoubleValueOrDefault(preReserveMemberDetialVO.getHeight(), 0.0)); // 身高
            row.getCell(3).setCellValue(getDoubleValueOrDefault(preReserveMemberDetialVO.getWeight(), 0.0)); // 体重
            row.getCell(5).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getVision(), "")); // 视力
            row.getCell(7).setCellValue(preReserveMemberDetialVO.getHasMedicalHistory() != null ? (preReserveMemberDetialVO.getHasMedicalHistory() == 1 ? "有" : "没有") : ""); // 是否有病史
            row = sheet.getRow(15);
            row.getCell(1).setCellValue(preReserveMemberDetialVO.getPhysicalCondition() != null ? (preReserveMemberDetialVO.getPhysicalCondition() == 1 ? "良好" : (preReserveMemberDetialVO.getPhysicalCondition() == 2 ? "一般" : "较差")) : ""); // 体能状况
            row.getCell(6).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getPsychologicalInterview(), "")); // 心理面试
            row = sheet.getRow(16);
            row.getCell(1).setCellValue(preReserveMemberDetialVO.getHasMilitaryTraining() != null ? (preReserveMemberDetialVO.getHasMilitaryTraining() == 1 ? "是" : "否") : ""); // 是否接受过军事训练
            row.getCell(4).setCellValue(getIntValueOrDefault(preReserveMemberDetialVO.getMilitaryTrainingDuration(), 0)); // 军事训练时长
            row.getCell(7).setCellValue(preReserveMemberDetialVO.getMilitaryClubLeaveDate() != null ? preReserveMemberDetialVO.getMilitaryClubLeaveDate().format(formatter) : ""); // 军事俱乐部离开日期
            row = sheet.getRow(17);
            row.getCell(1).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getMilitaryClubLeaveDevelop(), "")); // 退出社团发展情况

            // 填充服役信息
            row = sheet.getRow(19);
            row.getCell(1).setCellValue(preReserveMemberDetialVO.getIsServedInMilitary() != null ? (preReserveMemberDetialVO.getIsServedInMilitary() == 1 ? "是" : "否") : ""); // 是否服过兵役
            row.getCell(3).setCellValue(getIntValueOrDefault(preReserveMemberDetialVO.getMilitaryBranch(), 0)); // 军种
            row.getCell(5).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getUnitNumber(), "")); // 部队编号
            row.getCell(7).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getRankname(), "")); // 军衔

            row = sheet.getRow(20);
            row.getCell(1).setCellValue(preReserveMemberDetialVO.getFirstEnlistmentDate() != null ? preReserveMemberDetialVO.getFirstEnlistmentDate().format(formatter) : ""); // 初次入伍日期
            row.getCell(3).setCellValue(preReserveMemberDetialVO.getEnlistmentDate() != null ? preReserveMemberDetialVO.getEnlistmentDate().format(formatter) : ""); // 入伍日期
            row.getCell(5).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getEnlistmentPlace(), "")); // 入伍地点
            row.getCell(7).setCellValue(preReserveMemberDetialVO.getDischargeDate() != null ? preReserveMemberDetialVO.getDischargeDate().format(formatter) : ""); // 退役日期

            row = sheet.getRow(21);
            row.getCell(1).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getMilitarySpecialty(), "")); // 军事专业
            row.getCell(5).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getMilitaryPosition(), "")); // 军事职务
            row.getCell(7).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getAwards(), "")); // 获得奖项

            row = sheet.getRow(22);
            row.getCell(1).setCellValue(preReserveMemberDetialVO.getIsReservedMilitary() != null ? (preReserveMemberDetialVO.getIsReservedMilitary() == 1 ? "是" : "否") : ""); // 是否有预备役
            row.getCell(5).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getReservedPosition(), "")); // 预备役职务
            row.getCell(7).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getReservedSpecialty(), "")); // 预备役专业

            // 填充学习经历
            row = sheet.getRow(25);
            row.getCell(7).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getPrimarySchoolName(), "")); // 小学名称
            row.getCell(2).setCellValue(preReserveMemberDetialVO.getPrimarySchoolStartDate() != null ? preReserveMemberDetialVO.getPrimarySchoolStartDate().format(formatter) : ""); // 小学开始日期
            row.getCell(5).setCellValue(preReserveMemberDetialVO.getPrimarySchoolEndDate() != null ? preReserveMemberDetialVO.getPrimarySchoolEndDate().format(formatter) : ""); // 小学结束日期

            row = sheet.getRow(26);
            row.getCell(7).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getMiddleSchoolName(), "")); // 初中名称
            row.getCell(2).setCellValue(preReserveMemberDetialVO.getMiddleSchoolStartDate() != null ? preReserveMemberDetialVO.getMiddleSchoolStartDate().format(formatter) : ""); // 初中开始日期
            row.getCell(5).setCellValue(preReserveMemberDetialVO.getMiddleSchoolEndDate() != null ? preReserveMemberDetialVO.getMiddleSchoolEndDate().format(formatter) : ""); // 初中结束日期

            row = sheet.getRow(27);
            row.getCell(7).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getHighSchoolName(), "")); // 高中名称
            row.getCell(2).setCellValue(preReserveMemberDetialVO.getHighSchoolStartDate() != null ? preReserveMemberDetialVO.getHighSchoolStartDate().format(formatter) : ""); // 高中开始日期
            row.getCell(5).setCellValue(preReserveMemberDetialVO.getHighSchoolEndDate() != null ? preReserveMemberDetialVO.getHighSchoolEndDate().format(formatter) : ""); // 高中结束日期

            row = sheet.getRow(28);
            row.getCell(7).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getUniversityName(), "")); // 大学名称
            row.getCell(2).setCellValue(preReserveMemberDetialVO.getUniversityStartDate() != null ? preReserveMemberDetialVO.getUniversityStartDate().format(formatter) : ""); // 大学开始日期
            row.getCell(5).setCellValue(preReserveMemberDetialVO.getUniversityEndDate() != null ? preReserveMemberDetialVO.getUniversityEndDate().format(formatter) : ""); // 大学结束日期

            // 填充预征预储信息
            row = sheet.getRow(32);
            row.getCell(1).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getMilitarySkillsTraining(), "")); // 军事技能训练情况
            row = sheet.getRow(34);
            row.getCell(1).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getPoliticalTheoryLearningSituation(), "")); // 政治理论学习情况
            row = sheet.getRow(36);
            row.getCell(1).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getPhysicalFitnessTraining(), "")); // 体适能训练情况
            row = sheet.getRow(38);
            row.getCell(1).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getPhysicalExamination(), "")); // 体检检查情况
            row = sheet.getRow(40);
            row.getCell(1).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getPsychologicalTestSituation(), "")); // 心理测验情况
            row = sheet.getRow(41);
            row.getCell(1).setCellValue(getStringValueOrDefault(preReserveMemberDetialVO.getImages(), "")); // 相关图片
        } catch (IOException e) {
            throw new RuntimeException("下载头像图片失败", e);
        }
    }

    // 下载图片的辅助方法
    private byte[] downloadImage(String imageUrl) throws IOException {
        URL url = new URL(imageUrl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setDoInput(true);
        try (InputStream inputStream = connection.getInputStream()) {
            return inputStream.readAllBytes();  // 将图片数据转换为字节数组
        }
    }


    /*批量导出学生简略数据列表名单*/
    @Override
    public void getMembersExcelList(PreReserveMembersExcelDTO prmed, HttpServletResponse response) {
        //非空判断
        if (prmed.getHeads() == null) {
            throw new NullDataException();
        }
        //得到标题头
        String[] heads = prmed.getHeads();
        //小托峰转下划线处理
        prmed.setHeads(CamelToSnake.convertsToSnakeCases(heads));
        //查询数据库得到结果
        List<PreReservePageMemberVO> list = preReserveMemberMapper.getMembersExcel(prmed);

        // 处理 gender 字段
        for (PreReservePageMemberVO member : list) {
            if (member.getGender() != null) {
                member.setGender("0".equals(member.getGender()) ? "男" : "女");
            }
        }

        //Excel导出
        // 创建表头样式（居中）
        WriteCellStyle headStyle = new WriteCellStyle();
        headStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        // 创建内容样式（居中）
        WriteCellStyle contentStyle = new WriteCellStyle();
        contentStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        contentStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        // 应用样式策略
        HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headStyle, contentStyle);
        //包含列
        Set includeColumnFiledNames = new HashSet(Arrays.asList(heads));
        try {
            //获取输出流，输出
            EasyExcel.write(response.getOutputStream(), PreReservePageMemberVO.class)
                    .includeColumnFiledNames(includeColumnFiledNames)
                    .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 自动调整列宽
                    .registerWriteHandler(horizontalCellStyleStrategy) // 注册居中样式
                    .sheet("预储成员信息")
                    .doWrite(list);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /*分别导出多个学生Excel详细信息*/
    @Override
    public void getMembersExcelInfoList(PreReserveMembersExcelDTO preReserveMembersExcelDTO, HttpServletResponse response) {
        String[] studentIds = preReserveMembersExcelDTO.getStudentIds();
        if (studentIds == null || studentIds.length == 0) {
            throw new NullDataException();
        }
        try {
            //如果学生只有一个直接导出Excel
            if (studentIds.length == 1) {
                // 设置响应头，下载文件时的文件名为 selected_members_excel.zip
                response.setContentType("application/zip");
                response.setHeader("Content-Disposition", "attachment; filename=student_" + studentIds[0] + ".xlsx");

                // 得到学生对象信息
                PreReserveMemberDetialVO preReserveMemberDetialVO = getMemberDetialInfo(studentIds[0]);

                // 通过POI将数据写入Excel文件
                InputStream excelModuleStream = this.getClass().getClassLoader().getResourceAsStream("module/预储信息采集表.xlsx");
                XSSFWorkbook excel = new XSSFWorkbook(excelModuleStream);
                XSSFSheet sheet = excel.getSheet("Sheet1");

                // 填充数据
                createExcelSheet(sheet, preReserveMemberDetialVO);

                //写出
                excel.write(response.getOutputStream());

                // 关闭 Excel 文件流
                excel.close();
                excelModuleStream.close();

            }

            //多个学生时
            else {
                // 设置响应头，下载文件时的文件名为 selected_members_excel.zip
                response.setContentType("application/zip");
                response.setHeader("Content-Disposition", "attachment; filename=PreReserve_members_excel.zip");

                // 获取 ZIP 输出流
                ZipOutputStream zipOutputStream = new ZipOutputStream(response.getOutputStream());

                for (int i = 0; i < studentIds.length; i++) {
                    // 得到学生对象信息
                    PreReserveMemberDetialVO preReserveMemberDetialVO = getMemberDetialInfo(studentIds[i]);

                    // 通过POI将数据写入Excel文件
                    InputStream excelModuleStream = this.getClass().getClassLoader().getResourceAsStream("module/预储信息采集表.xlsx");
                    XSSFWorkbook excel = new XSSFWorkbook(excelModuleStream);
                    XSSFSheet sheet = excel.getSheet("Sheet1");

                    // 填充数据
                    createExcelSheet(sheet, preReserveMemberDetialVO);

                    // 将 Excel 文件保存到 ZIP 文件中
                    String excelFileName = "student_" + studentIds[i] + ".xlsx";
                    ZipEntry zipEntry = new ZipEntry(excelFileName);
                    zipOutputStream.putNextEntry(zipEntry);

                    // 将 Excel 写入到 ZIP 输出流
                    ByteArrayOutputStream excelByteStream = new ByteArrayOutputStream();
                    excel.write(excelByteStream);
                    zipOutputStream.write(excelByteStream.toByteArray());

                    // 关闭当前条目的流
                    zipOutputStream.closeEntry();

                    // 关闭 Excel 文件流
                    excel.close();
                    excelModuleStream.close();
                }

                // 完成 ZIP 文件的输出
                zipOutputStream.finish();
                zipOutputStream.close();

            }

        } catch (IOException e) {
            throw new RuntimeException("导出失败", e);
        }
    }


    //分别导出多个学生详细信息PDF
    @Override
    public void getMembersPDFInfoList(PreReserveMembersExcelDTO preReserveMembersExcelDTO, HttpServletResponse response) {
        String[] studentIds = preReserveMembersExcelDTO.getStudentIds();
        if (studentIds == null || studentIds.length == 0) {
            throw new NullDataException();
        }

        try {
            // 加载中文字体
            BaseFont baseFont = BaseFont.createFont("zbt-server/src/main/resources/fonts/STFANGSO.TTF", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);

            // 如果只有一个学生，直接导出 PDF 文件
            if (studentIds.length == 1) {
                // 设置响应头，下载文件时的文件名为 student_<studentId>.pdf
                response.setContentType("application/pdf");
                response.setHeader("Content-Disposition", "attachment; filename=student_" + studentIds[0] + ".pdf");

                // 得到学生对象信息
                PreReserveMemberDetialVO memberInfo = getMemberDetialInfo(studentIds[0]);

                // 获取 PDF 模板
                PdfReader pdfReader = new PdfReader(Objects.requireNonNull(this.getClass().getClassLoader().getResourceAsStream("module/预储信息采集表.pdf")));

                // 根据模板生成 PDF
                PdfStamper stamper = new PdfStamper(pdfReader, response.getOutputStream());
                AcroFields pdfForm = stamper.getAcroFields();
                pdfForm.addSubstitutionFont(baseFont);

                // 装配数据
                Map<String, Object> pdfData = new HashMap<>();
                createPdfDate(pdfData, memberInfo);

                // 遍历数据，填充 PDF 表单
                for (String key : pdfData.keySet()) {
                    // 图片要单独处理
                    if ("imgUrl".equals(key) || "images".equals(key)) {
                        int pageNo = pdfForm.getFieldPositions(key).get(0).page;
                        Rectangle signRect = pdfForm.getFieldPositions(key).get(0).position;
                        float x = signRect.getLeft();
                        float y = signRect.getBottom();
                        String studentImage = pdfData.get(key).toString();
                        if (studentImage != null && !studentImage.isEmpty()) {
                            PdfContentByte under = null; // 将 under 声明移到 try 块外部
                            try {
                                // 获取图片页面
                                under = stamper.getOverContent(pageNo); // 在 try 块中赋值
                                // 根据路径或 URL 读取图片
                                Image image = Image.getInstance(studentImage);
                                // 图片大小自适应
                                image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                                // 添加图片
                                image.setAbsolutePosition(x, y);
                                under.addImage(image);
                            } catch (IOException e) {
                                // 处理图片加载失败的情况
                                log.error("图片{}加载失败，使用默认图片", studentImage);
                                // 使用默认图片
                                try {
                                    Image defaultImage = Image.getInstance("D:/iT/project/ZBT/zbt-admin/zbt-server/src/main/resources/img/default.jpg");
                                    defaultImage.scaleToFit(signRect.getWidth(), signRect.getHeight());
                                    defaultImage.setAbsolutePosition(x, y);
                                    under.addImage(defaultImage);
                                } catch (IOException | DocumentException ex) {
                                    log.error("默认图片加载失败", ex);
                                }
                            }
                        }
                    }
                    // 设置普通文本数据
                    else {
                        // 设置普通文本数据
                        pdfForm.setFieldProperty(key, "textfont", baseFont, null);
                        pdfForm.setFieldProperty(key, "textsize", 7f, null);
                        pdfForm.setField(key, pdfData.get(key).toString());
                    }
                }

                // 添加水印
                addWatermark(stamper, "GUFE-ZBT");

                // 设置 PDF 不可修改
                stamper.setFormFlattening(true);
                stamper.close();

                log.info("*****************************PDF导出成功*********************************");

            }

            //多个学生用zip
            else {
                // 设置响应头，下载文件时的文件名为 preReserve_members_PDF.zip
                response.setContentType("application/zip");
                response.setHeader("Content-Disposition", "attachment; filename=preReserve_members_PDF.zip");

                // 获取 ZIP 输出流
                ZipOutputStream zipOutputStream = new ZipOutputStream(response.getOutputStream());

                for (int i = 0; i < studentIds.length; i++) {
                    // 创建新的 ByteArrayOutputStream
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();

                    // 得到学生对象信息
                    PreReserveMemberDetialVO memberInfo = getMemberDetialInfo(studentIds[i]);

                    // 获取 PDF 模板
                    PdfReader pdfReader = new PdfReader(Objects.requireNonNull(this.getClass().getClassLoader().getResourceAsStream("module/预储信息采集表.pdf")));

                    // 根据模板生成 PDF
                    PdfStamper stamper = new PdfStamper(pdfReader, bos);
                    AcroFields pdfForm = stamper.getAcroFields();
                    pdfForm.addSubstitutionFont(baseFont);

                    // 装配数据
                    Map<String, Object> pdfData = new HashMap<>();
                    createPdfDate(pdfData, memberInfo);

                    // 遍历数据，填充 PDF 表单
                    for (String key : pdfData.keySet()) {
                        // 图片要单独处理
                        if ("imgUrl".equals(key) || "images".equals(key)) {
                            int pageNo = pdfForm.getFieldPositions(key).get(0).page;
                            Rectangle signRect = pdfForm.getFieldPositions(key).get(0).position;
                            float x = signRect.getLeft();
                            float y = signRect.getBottom();
                            String studentImage = pdfData.get(key).toString();
                            if (studentImage != null && !studentImage.isEmpty()) {
                                PdfContentByte under = null; // 将 under 声明移到 try 块外部
                                try {
                                    // 获取图片页面
                                    under = stamper.getOverContent(pageNo); // 在 try 块中赋值
                                    // 根据路径或 URL 读取图片
                                    Image image = Image.getInstance(studentImage);
                                    // 图片大小自适应
                                    image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                                    // 添加图片
                                    image.setAbsolutePosition(x, y);
                                    under.addImage(image);
                                } catch (IOException e) {
                                    // 处理图片加载失败的情况
                                    log.error("图片{}加载失败，使用默认图片", studentImage);
                                    // 使用默认图片
                                    try {
                                        Image defaultImage = Image.getInstance("D:/iT/project/ZBT/zbt-admin/zbt-server/src/main/resources/img/default.jpg");
                                        defaultImage.scaleToFit(signRect.getWidth(), signRect.getHeight());
                                        defaultImage.setAbsolutePosition(x, y);
                                        under.addImage(defaultImage);
                                    } catch (IOException | DocumentException ex) {
                                        log.error("默认图片加载失败", ex);
                                    }
                                }
                            }
                        }
                        // 设置普通文本数据
                        else {
                            // 设置普通文本数据
                            pdfForm.setFieldProperty(key, "textfont", baseFont, null);
                            pdfForm.setFieldProperty(key, "textsize", 7f, null);
                            pdfForm.setField(key, pdfData.get(key).toString());
                        }
                    }

                    // 添加水印
                    addWatermark(stamper, "GUFE-ZBT");

                    // 设置 PDF 不可修改
                    stamper.setFormFlattening(true);
                    stamper.close();

                    // 将 PDF 文件写入 ZIP
                    String pdfFileName = "student_" + studentIds[i] + ".pdf";
                    ZipEntry zipEntry = new ZipEntry(pdfFileName);
                    zipOutputStream.putNextEntry(zipEntry);
                    zipOutputStream.write(bos.toByteArray());

                    zipOutputStream.closeEntry();

                    // 关闭资源
                    bos.close();
                }

                // 完成 ZIP 文件输出
                zipOutputStream.finish();
                zipOutputStream.close();
                log.info("*****************************PDF导出成功*********************************");
            }

        } catch (IOException | DocumentException e) {
            throw new RuntimeException("导出 PDF 失败", e);
        }
    }

    //更新预储成员信息
    @Override
    public void updateInfoDTO(UpdateInfoDTO updateInfoDTO) {

        PreReserveInfoDTO preReserveInfoDTO = updateInfoDTO.getPreReserveInfoDTO();
        preReserveInfoDTO.setUserId(Integer.valueOf(updateInfoDTO.getUserId()));

        System.out.println(preReserveInfoDTO);

        preReserveMemberMapper.updateInfoDTO(preReserveInfoDTO);
    }

    // 添加水印
    private void addWatermark(PdfStamper stamper, String watermarkText) throws DocumentException, IOException {
        PdfContentByte content;
        BaseFont baseFont = BaseFont.createFont(BaseFont.HELVETICA_BOLD, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);
        int totalPages = stamper.getReader().getNumberOfPages();

        for (int i = 1; i <= totalPages; i++) {
            content = stamper.getUnderContent(i); // 在内容下方添加水印
            content.beginText();
            content.setColorFill(BaseColor.LIGHT_GRAY);
            content.setFontAndSize(baseFont, 60); // 设置水印字体大小
            // 设置水印位置和角度
            content.showTextAligned(Element.ALIGN_CENTER, watermarkText, 297.5f, 421, 45); // 居中位置，45度倾斜
            content.endText();
        }
    }

    //创建map数据供写入pdf
    private void createPdfDate(Map<String, Object> pdfData, PreReserveMemberDetialVO memberInfo) {
        pdfData.put("name", getStringValueOrDefault(memberInfo.getName(), ""));
        pdfData.put("gender", getIntValueOrDefault(memberInfo.getGender(), 0) == 1 ? "男" : "女");
        pdfData.put("idCard", getStringValueOrDefault(memberInfo.getIdCard(), ""));
        pdfData.put("politicalAffiliation", getStringValueOrDefault(memberInfo.getPoliticalAffiliation(), ""));
        pdfData.put("profilePicture", getStringValueOrDefault(memberInfo.getProfilePicture(), ""));
        pdfData.put("birthDate", getStringValueOrDefault(String.valueOf(memberInfo.getBirthDate()), ""));
        pdfData.put("nationality", getStringValueOrDefault(memberInfo.getNationality(), ""));
        pdfData.put("maritalStatus", getIntValueOrDefault(memberInfo.getMaritalStatus(), 0) == 1 ? "未婚" : "已婚");
        pdfData.put("religiousAffiliation", getStringValueOrDefault(memberInfo.getReligiousAffiliation(), ""));
        pdfData.put("nativePlace", getStringValueOrDefault(memberInfo.getNativePlace(), ""));
        pdfData.put("homeAddress", getStringValueOrDefault(memberInfo.getHomeAddress(), ""));
        pdfData.put("mailingAddress", getStringValueOrDefault(memberInfo.getMailingAddress(), ""));
        pdfData.put("college", getStringValueOrDefault(memberInfo.getCollege(), ""));
        pdfData.put("major", getStringValueOrDefault(memberInfo.getMajor(), ""));
        pdfData.put("studentId", getStringValueOrDefault(memberInfo.getStudentId(), ""));
        pdfData.put("scienceOrHumanities", getIntValueOrDefault(memberInfo.getScienceOrHumanities(), 0) == 1 ? "理科" : "文科");
        pdfData.put("grade", getStringValueOrDefault(String.valueOf(memberInfo.getGrade()), ""));
        pdfData.put("className", getStringValueOrDefault(memberInfo.getClassName(), ""));
        pdfData.put("contactInformation", getStringValueOrDefault(memberInfo.getTelephone(), ""));
        pdfData.put("qq", getStringValueOrDefault(memberInfo.getQq(), ""));
        pdfData.put("highSchoolPhysicalGrade", getStringValueOrDefault(String.valueOf(memberInfo.getHighSchoolPhysicalGrade()), ""));
        pdfData.put("universityPhysicalGrade", getStringValueOrDefault(String.valueOf(memberInfo.getUniversityPhysicalGrade()), ""));
        pdfData.put("professionalCertificates", getStringValueOrDefault(memberInfo.getProfessionalCertificates(), ""));
        pdfData.put("classPosition", getStringValueOrDefault(memberInfo.getClassPosition(), ""));
        pdfData.put("clubName", getStringValueOrDefault(memberInfo.getClubName(), ""));
        pdfData.put("clubJoinDate", getStringValueOrDefault(String.valueOf(memberInfo.getClubJoinDate()), ""));
        pdfData.put("clubLeaveDate", getStringValueOrDefault(String.valueOf(memberInfo.getClubLeaveDate()), ""));
        pdfData.put("highSchoolName", getStringValueOrDefault(memberInfo.getHighSchoolName(), ""));
        pdfData.put("highSchoolAddress", getStringValueOrDefault(memberInfo.getHighSchoolAddress(), ""));
        pdfData.put("highSchoolSubjectType", getIntValueOrDefault(memberInfo.getHighSchoolSubjectType(), 0) == 1 ? "理科" : "文科");
        pdfData.put("isMilitaryClubMember", getIntValueOrDefault(memberInfo.getIsMilitaryClubMember(), 0) == 1 ? "是" : "否");
        pdfData.put("militaryClubJoinDate", getStringValueOrDefault(String.valueOf(memberInfo.getMilitaryClubJoinDate()), ""));
        pdfData.put("militaryClubName", getStringValueOrDefault(memberInfo.getMilitaryClubName(), ""));
        pdfData.put("militaryClubPosition", getStringValueOrDefault(memberInfo.getMilitaryClubPosition(), ""));
        pdfData.put("height", getDoubleValueOrDefault(memberInfo.getHeight(), 0.0));
        pdfData.put("weight", getDoubleValueOrDefault(memberInfo.getWeight(), 0.0));
        pdfData.put("vision", getStringValueOrDefault(memberInfo.getVision(), ""));
        pdfData.put("hasMedicalHistory", getIntValueOrDefault(memberInfo.getHasMedicalHistory(), 0) == 1 ? "有" : "没有");
        pdfData.put("physicalCondition", getStringValueOrDefault(String.valueOf(memberInfo.getPhysicalCondition()), ""));
        pdfData.put("psychologicalInterview", getStringValueOrDefault(memberInfo.getPsychologicalInterview(), ""));
        pdfData.put("hasMilitaryTraining", getIntValueOrDefault(memberInfo.getHasMilitaryTraining(), 0) == 1 ? "是" : "否");
        pdfData.put("militaryTrainingDuration", getStringValueOrDefault(String.valueOf(memberInfo.getMilitaryTrainingDuration()), ""));
        pdfData.put("militaryClubLeaveDate", getStringValueOrDefault(String.valueOf(memberInfo.getMilitaryClubLeaveDate()), ""));
        pdfData.put("militaryClubLeaveDevelop", getStringValueOrDefault(memberInfo.getMilitaryClubLeaveDevelop(), ""));
        pdfData.put("isServedInMilitary", getIntValueOrDefault(memberInfo.getIsServedInMilitary(), 0) == 1 ? "是" : "否");
        pdfData.put("militaryBranch", getStringValueOrDefault(String.valueOf(memberInfo.getMilitaryBranch()), ""));
        pdfData.put("unitNumber", getStringValueOrDefault(memberInfo.getUnitNumber(), ""));
        pdfData.put("rankname", getStringValueOrDefault(memberInfo.getRankname(), ""));
        pdfData.put("firstEnlistmentDate", getStringValueOrDefault(String.valueOf(memberInfo.getFirstEnlistmentDate()), ""));
        pdfData.put("enlistmentDate", getStringValueOrDefault(String.valueOf(memberInfo.getEnlistmentDate()), ""));
        pdfData.put("enlistmentPlace", getStringValueOrDefault(memberInfo.getEnlistmentPlace(), ""));
        pdfData.put("dischargeDate", getStringValueOrDefault(String.valueOf(memberInfo.getDischargeDate()), ""));
        pdfData.put("militarySpecialty", getStringValueOrDefault(memberInfo.getMilitarySpecialty(), ""));
        pdfData.put("militaryPosition", getStringValueOrDefault(memberInfo.getMilitaryPosition(), ""));
        pdfData.put("awards", getStringValueOrDefault(memberInfo.getAwards(), ""));
        pdfData.put("isReservedMilitary", getIntValueOrDefault(memberInfo.getIsReservedMilitary(), 0) == 1 ? "是" : "否");
        pdfData.put("ReservedPosition", getStringValueOrDefault(memberInfo.getReservedPosition(), ""));
        pdfData.put("ReservedSpecialty", getStringValueOrDefault(memberInfo.getReservedSpecialty(), ""));
        pdfData.put("imgUrl", getStringValueOrDefault(memberInfo.getProfilePicture(), ""));
        pdfData.put("images", getStringValueOrDefault(memberInfo.getImages(), ""));
    }


    /*
    字段非空判断方法
    * */
    private Integer getIntValueOrDefault(Integer value, Integer defaultValue) {
        return value != null ? value : defaultValue;
    }

    private Double getDoubleValueOrDefault(Double value, Double defaultValue) {
        return value != null ? value : defaultValue;
    }

    private String getStringValueOrDefault(String value, String defaultValue) {
        if (value == null) {
            return defaultValue;
        } else if ("null".equals(value)) {
            return defaultValue;
        } else {
            return value;
        }
    }


}
